package com.nineclock.auth.intergration.aop;

import com.nineclock.auth.intergration.threadLocal.UserHolder;
import com.nineclock.common.entity.Result;
import com.nineclock.common.entity.UserInfo;

import com.nineclock.auth.intergration.entity.IntergrationAuthenticationEntity;
import com.nineclock.auth.intergration.entity.NcOauthTokenDTO;
import com.nineclock.auth.intergration.threadLocal.IntergrationAuthenticationHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * aop切面类
 */
@Aspect
@Component
@Slf4j
public class AuthTokenAspect {


    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
    public Object postHandleAuthTokenResult(ProceedingJoinPoint joinPoint) {
        log.info("AOP认证请求拦截");

        Result<NcOauthTokenDTO> result = null;

        Object returnObj = null;

        try {
            // 1.获取到request对象
            HttpServletRequest request = ((ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes()).getRequest();


            // 2.获取请求参数
            IntergrationAuthenticationEntity entity = new IntergrationAuthenticationEntity();
            String authType = request.getParameter("auth_type");
            entity.setAuthType(authType);
            entity.setAuthParameters(request.getParameterMap());

            // 4.往ThreadLocal中存数据
            IntergrationAuthenticationHolder.set(entity);

            // 5.调用目标方法执行
            returnObj = joinPoint.proceed();


            if (returnObj != null) {
                ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) returnObj;

                OAuth2AccessToken oAuth2AccessToken = responseEntity.getBody();
                NcOauthTokenDTO ncOauthTokenDTO = new NcOauthTokenDTO();
                ncOauthTokenDTO.setOauth2AccessToken(oAuth2AccessToken);
                ncOauthTokenDTO.setUser(UserHolder.get());
                result = Result.success(ncOauthTokenDTO);
            }


        } catch (Throwable throwable) {

            log.error("认证出现异常: ", throwable);

            result = Result.errorCodeMessage(401, throwable.getMessage());

            return ResponseEntity.status(result.getCode()).body(result);


        } finally {

            // 使用完threadLocal后，要进行删除，否则容易导致内存溢出
            IntergrationAuthenticationHolder.remove();
            UserHolder.remove();
        }

        return ResponseEntity.ok(result);

    }
}
